﻿using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace Keithley_2400
{
    public class Keithley
    {
        private SerialPort serialPort = null;
        string command = null;
        public int Connect(string portName, int baudRate_selection, int parity_selection, int dataBits_selection, int stopBits_selection) // 连接Keithley的函数
        {
            int baudRate = 9600;
            Parity parity = Parity.None;
            int dataBits = 8;
            StopBits stopBits = StopBits.One;
            switch (baudRate_selection)// 波特率
            {
                case 0:
                    baudRate = 300;
                    break;
                case 1:
                    baudRate = 1200;
                    break;
                case 2:
                    baudRate = 2400;
                    break;
                case 3:
                    baudRate = 4800;
                    break;
                case 4:
                    baudRate = 9600;
                    break;
                case 5:
                    baudRate = 14400;
                    break;
                case 6:
                    baudRate = 19200;
                    break;
                case 7:
                    baudRate = 38400;
                    break;
                case 8:
                    baudRate = 57600;
                    break;
                case 9:
                    baudRate = 115200;
                    break;
            }
            switch (parity_selection)// 奇偶校验位
            {
                case 0:
                    parity = Parity.None;
                    break;
                case 1:
                    parity = Parity.Odd;
                    break;
                case 2:
                    parity = Parity.Even;
                    break;
                case 3:
                    parity = Parity.Mark;
                    break;
                case 4:
                    parity = Parity.Space;
                    break;
            }
            switch (dataBits_selection)// 数据位
            {
                case 0:
                    dataBits = 5;
                    break;
                case 1:
                    dataBits = 6;
                    break;
                case 2:
                    dataBits = 7;
                    break;
                case 3:
                    dataBits = 8;
                    break;
            }
            switch (stopBits_selection)// 停止位
            {
                case 0:
                    stopBits = StopBits.None;
                    break;
                case 1:
                    stopBits = StopBits.One;
                    break;
                case 2:
                    stopBits = StopBits.Two;
                    break;
                case 3:
                    stopBits = StopBits.OnePointFive;
                    break;
            }

            try
            {
                serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
                serialPort.Open();
                return 1;
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
            return 0;
        }
        public int Disconnect() // 断开Keithley的函数
        {
            try
            {
                serialPort.Close();
                return 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
            return 0;
        }
        public string GetRangeUnit(string range)// 获得输出电压(流)和测量电压(流)的单位的函数
        {
            string unit = null;
            int cut_count = 0;
            for (int i = 0;i<range.Length;i++)
            {
                if (char.IsDigit(range[i]))// 判断字符串第i位字符是不是数字字符
                    cut_count++;
                else
                    break;
            }
            unit = range.Substring(cut_count,(range.Length - cut_count));// 取除前面数字外的字符，即单位
            return unit;
        }
        private double GetRangeValue(string range)// 获得所选量程的数值(除单位)的函数
        {
            double value = 0;
            string range_value = null;
            int cut_count = 0;
            for (int i = 0; i < range.Length; i++)
            {
                if (char.IsDigit(range[i]))// 判断字符串第i位字符是不是数字字符
                    cut_count++;
                else
                    break;
            }
            range_value=range.Substring(0,cut_count);// 取除后面单位外的字符，即数字字符
            value = double.Parse(range_value);
            return value;
        }
        public void SaveParameters(int source_mode, string source_range, string source_level_value, string measure_cmp_value, int measure_cmp_unit)// 保存参数的函数，即将设置好的参数根据规则转换后写入串口
        {            
            string source_range_unit = null;
            double source_range_value = 0;// 写入串口的输出量程
            double source_level_value_transformed = 0;
            double measure_cmp_value_transformed = 0;

            if (source_mode == 0)// 恒压模式下的转换与写入
            {
                command = "*RST";// 恢复默认
                serialPort.WriteLine(command);
                command = ":SOUR:FUNC VOLT";  // 设置源表功能为电压模式
                serialPort.WriteLine(command);
                command = ":SOUR:VOLT:MODE FIX";  // 设置为恒压模式
                serialPort.WriteLine(command);

                source_range_unit = GetRangeUnit(source_range);// 获得选择的量程的单位(量程的单位跟输出电压(流)的单位一样)
                source_range_value = GetRangeValue(source_range);
                if (source_range_unit == "mV")// 写入串口的值必须以“V”为单位
                    source_range_value = source_range_value * 1e-3;
                command = ":SOUR:VOLT:RANG " + source_range_value;// 设置电压输出量程
                serialPort.WriteLine(command);

                try
                {
                    source_level_value_transformed = double.Parse(source_level_value);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error");
                }
                if (source_range_unit == "mV")// 写入串口的值必须以“V”为单位
                    source_level_value_transformed = source_level_value_transformed * 1e-3;
                if (source_level_value_transformed <= source_range_value) // 设置的输出值是否超出所选输出量程
                {
                    command = ":SOUR:VOLT:LEV " + source_level_value_transformed;// 设置输出电压
                    serialPort.WriteLine(command);
                }
                else
                {
                    MessageBox.Show("输出值超出输出量程");
                }

                command = ":SENS:FUNC \"CURR\"";// 设置源表功能为电流测量模式
                serialPort.WriteLine(command);

                try
                {
                    measure_cmp_value_transformed = double.Parse(measure_cmp_value);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error");
                }
                if (measure_cmp_unit == 0)// μA
                    measure_cmp_value_transformed = measure_cmp_value_transformed * 1e-6;
                else if (measure_cmp_unit == 1)// mA
                    measure_cmp_value_transformed = measure_cmp_value_transformed * 1e-3;              
                command = ":SENS:CURR:PROT " + measure_cmp_value_transformed;// 设置测量限电流
                serialPort.WriteLine(command);

                command = ":SENS:CURR:RANG " + measure_cmp_value_transformed;// 设置初始量程
                serialPort.WriteLine(command);
                command = ":SENS:CURR:RANG:AUTO ON";//设置自动测量量程
                serialPort.WriteLine(command);
            }
            else if (source_mode == 1)// 恒流模式下的转换与写入
            {
                command = "*RST";// 恢复默认
                serialPort.WriteLine(command);
                command = ":SOUR:FUNC CURR";  // 设置源表功能为电流模式
                serialPort.WriteLine(command);
                command = ":SOUR:CURR:MODE FIX";  // 设置为恒流模式
                serialPort.WriteLine(command);

                source_range_unit = GetRangeUnit(source_range);// 获得选择的量程的单位(量程的单位跟输出电压(流)的单位一样)
                source_range_value = GetRangeValue(source_range);
                if (source_range_unit == "μA")// 写入串口的值必须以“A”为单位
                    source_range_value = source_range_value * 1e-6;
                else if (source_range_unit == "mA")
                    source_range_value = source_range_value * 1e-3;
                command = ":SOUR:CURR:RANG " + source_range_value;// 设置电压输出量程
                serialPort.WriteLine(command);

                try
                {
                    source_level_value_transformed = double.Parse(source_level_value);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error");
                }
                if (source_range_unit == "μA")// 写入串口的值必须以“A”为单位
                    source_level_value_transformed = source_level_value_transformed * 1e-6;
                else if (source_range_unit == "mA")
                    source_level_value_transformed = source_level_value_transformed * 1e-3;
                if (source_level_value_transformed <= source_range_value) // 设置的输出值是否超出所选输出量程
                {
                    command = ":SOUR:CURR:LEV " + source_level_value_transformed;// 设置输出电流
                    serialPort.WriteLine(command);
                }
                else
                {
                    MessageBox.Show("输出值超出输出量程");
                }

                command = ":SENS:FUNC \"VOLT\"";// 设置源表功能为电压测量模式
                serialPort.WriteLine(command);

                try
                {
                    measure_cmp_value_transformed = double.Parse(measure_cmp_value);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error");
                }
                if (measure_cmp_unit == 0)// mV
                    measure_cmp_value_transformed = measure_cmp_value_transformed * 1e-3;
                command = ":SENS:VOLT:RANG " + measure_cmp_value_transformed;// 设置初始量程
                serialPort.WriteLine(command);
                command = ":SENS:VOLT:RANG:AUTO ON";//设置自动测量量程
                serialPort.WriteLine(command);
                command = ":SENS:VOLT:PROT " + measure_cmp_value_transformed;// 设置测量限电压
                serialPort.WriteLine(command);               
            }          
        }
        public int Output()
        {
            try
            {
                command = ":OUTP ON";  // 打开输出
                serialPort.WriteLine(command);
                return 1;
            }
            catch (Exception ex) 
            {
                MessageBox.Show(ex.Message, "Error");
            }
            return 0;
        }
        public int StopOutput()
        {
            try
            {
                command = ":OUTP OFF";  // 关闭输出
                serialPort.WriteLine(command);
                return 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error");
            }
            return 0;
        }
        public string GetData()
        {
            string data = null;

            command = ":READ?";
            serialPort.WriteLine(command);
            data = serialPort.ReadTo("\r");

            return data;
        }       
    }
}
